#include "grpc_client.h"
#include "exceptions.h"
#include "proto/kwdb.pb.h"
#include "proto/kwdb.grpc.pb.h"

#include <grpcpp/grpcpp.h>
#include <grpcpp/create_channel.h>
#include <grpcpp/security/credentials.h>

#include <sstream>

namespace kwdb {

// PIMPL实现类 - 包含gRPC实现细节
class GrpcClientImpl {
public:
    std::shared_ptr<::grpc::Channel> channel;
    std::unique_ptr<kwdb::grpc::KWDBService::Stub> stub;
    
    GrpcClientImpl() = default;
    ~GrpcClientImpl() = default;
};

GrpcClient::GrpcClient(const ClientConfig& config)
    : config_(config)
    , impl_(std::make_unique<GrpcClientImpl>())
    , connected_(false) {
}

GrpcClient::~GrpcClient() {
    disconnect();
}

void GrpcClient::connect() {
    try {
        impl_->channel = createChannel();
        if (!impl_->channel) {
            throw ConnectionException("无法创建gRPC通道");
        }
        
        // 创建gRPC stub
        impl_->stub = kwdb::grpc::KWDBService::NewStub(impl_->channel);
        if (!impl_->stub) {
            throw ConnectionException("无法创建gRPC Stub");
        }
        
        connected_ = true;
    } catch (const std::exception& e) {
        throw ConnectionException("gRPC连接失败: " + std::string(e.what()));
    }
}

void GrpcClient::disconnect() {
    connected_ = false;
    if (impl_) {
        impl_->stub.reset();
        impl_->channel.reset();
    }
}

void GrpcClient::write(const DataPoint& dataPoint) {
    if (!connected_) {
        throw WriteException("gRPC客户端未连接");
    }
    
    try {
        // 这里需要根据实际的gRPC生成代码调整
        // WriteRequest request;
        // request.add_points()->CopyFrom(toProto(dataPoint));
        // request.set_compress(config_.isEnableCompression());
        // request.set_client_id(config_.getClientId());
        
        // grpc::ClientContext context;
        // WriteResponse response;
        
        // grpc::Status status = stub_->Write(&context, request, &response);
        // handleGrpcStatus(status);
        
        // 临时实现，实际需要gRPC生成代码
        throw WriteException("gRPC写入功能需要生成代码后实现");
    } catch (const std::exception& e) {
        throw WriteException("写入失败: " + std::string(e.what()));
    }
}

void GrpcClient::writeBatch(const std::vector<DataPoint>& dataPoints) {
    if (!connected_) {
        throw WriteException("gRPC客户端未连接");
    }
    
    try {
        // 这里需要根据实际的gRPC生成代码调整
        // WriteBatchRequest request;
        // for (const auto& dataPoint : dataPoints) {
        //     request.add_points()->CopyFrom(toProto(dataPoint));
        // }
        // request.set_compress(config_.isEnableCompression());
        // request.set_client_id(config_.getClientId());
        // request.set_batch_size(dataPoints.size());
        // request.set_timeout_ms(config_.getBatchTimeout());
        
        // grpc::ClientContext context;
        // WriteResponse response;
        
        // grpc::Status status = stub_->WriteBatch(&context, request, &response);
        // handleGrpcStatus(status);
        
        // 临时实现，实际需要gRPC生成代码
        throw WriteException("gRPC批量写入功能需要生成代码后实现");
    } catch (const std::exception& e) {
        throw WriteException("批量写入失败: " + std::string(e.what()));
    }
}

void GrpcClient::writeStream(const std::vector<DataPoint>& dataPoints) {
    if (!connected_) {
        throw WriteException("gRPC客户端未连接");
    }
    
    try {
        // 这里需要根据实际的gRPC生成代码调整
        // grpc::ClientContext context;
        // std::unique_ptr<grpc::ClientWriter<WriteRequest>> writer(
        //     stub_->WriteStream(&context, &response));
        
        // for (const auto& dataPoint : dataPoints) {
        //     WriteRequest request;
        //     request.add_points()->CopyFrom(toProto(dataPoint));
        //     request.set_compress(config_.isEnableCompression());
        //     request.set_client_id(config_.getClientId());
        //     
        //     if (!writer->Write(request)) {
        //         break;
        //     }
        // }
        // writer->WritesDone();
        
        // grpc::Status status = writer->Finish();
        // handleGrpcStatus(status);
        
        // 临时实现，实际需要gRPC生成代码
        throw WriteException("gRPC流式写入功能需要生成代码后实现");
    } catch (const std::exception& e) {
        throw WriteException("流式写入失败: " + std::string(e.what()));
    }
}

QueryResult GrpcClient::query(const std::string& sql) {
    if (!connected_) {
        throw QueryException("gRPC客户端未连接");
    }
    
    try {
        // 这里需要根据实际的gRPC生成代码调整
        // QueryRequest request;
        // request.set_sql(sql);
        // request.set_client_id(config_.getClientId());
        // request.set_limit(1000); // 默认限制
        // request.set_stream(false);
        
        // grpc::ClientContext context;
        // QueryResponse response;
        
        // grpc::Status status = stub_->Query(&context, request, &response);
        // handleGrpcStatus(status);
        
        // return fromProto(response);
        
        // 临时实现，实际需要gRPC生成代码
        throw QueryException("gRPC查询功能需要生成代码后实现");
    } catch (const std::exception& e) {
        throw QueryException("查询失败: " + std::string(e.what()));
    }
}

QueryResult GrpcClient::queryStream(const std::string& sql) {
    if (!connected_) {
        throw QueryException("gRPC客户端未连接");
    }
    
    try {
        // 这里需要根据实际的gRPC生成代码调整
        // QueryRequest request;
        // request.set_sql(sql);
        // request.set_client_id(config_.getClientId());
        // request.set_stream(true);
        
        // grpc::ClientContext context;
        // std::unique_ptr<grpc::ClientReader<QueryResponse>> reader(
        //     stub_->QueryStream(&context, request));
        
        // QueryResponse response;
        // std::vector<std::shared_ptr<QueryRow>> allRows;
        // std::vector<std::string> columns;
        
        // while (reader->Read(&response)) {
        //     // 处理流式响应
        //     // 这里需要根据实际的gRPC生成代码调整
        // }
        
        // grpc::Status status = reader->Finish();
        // handleGrpcStatus(status);
        
        // 临时实现，实际需要gRPC生成代码
        throw QueryException("gRPC流式查询功能需要生成代码后实现");
    } catch (const std::exception& e) {
        throw QueryException("流式查询失败: " + std::string(e.what()));
    }
}

bool GrpcClient::healthCheck() {
    if (!connected_) {
        return false;
    }
    
    try {
        // 这里需要根据实际的gRPC生成代码调整
        // HealthRequest request;
        // request.set_service("KWDBService");
        
        // grpc::ClientContext context;
        // HealthResponse response;
        
        // grpc::Status status = stub_->HealthCheck(&context, request, &response);
        // return status.ok() && response.status() == HealthResponse::SERVING;
        
        // 临时实现，实际需要gRPC生成代码
        return true;
    } catch (const std::exception& e) {
        return false;
    }
}

std::string GrpcClient::getStats() {
    if (!connected_) {
        return "{}";
    }
    
    try {
        // 这里需要根据实际的gRPC生成代码调整
        // StatsRequest request;
        // request.set_client_id(config_.getClientId());
        
        // grpc::ClientContext context;
        // StatsResponse response;
        
        // grpc::Status status = stub_->GetStats(&context, request, &response);
        // if (status.ok()) {
        //     // 返回统计信息JSON
        //     return response.DebugString();
        // }
        
        // 临时实现，实际需要gRPC生成代码
        return "{}";
    } catch (const std::exception& e) {
        return "{}";
    }
}

std::shared_ptr<::grpc::Channel> GrpcClient::createChannel() {
    std::string target = config_.getHost() + ":" + std::to_string(config_.getPort());
    
    ::grpc::ChannelArguments args;
    args.SetMaxReceiveMessageSize(config_.getMaxInboundMessageSize());
    args.SetMaxSendMessageSize(config_.getMaxInboundMessageSize());
    
    if (config_.isKeepAlive()) {
        args.SetInt(GRPC_ARG_KEEPALIVE_TIME_MS, config_.getKeepAliveTime() * 1000);
        args.SetInt(GRPC_ARG_KEEPALIVE_TIMEOUT_MS, config_.getKeepAliveTimeout() * 1000);
        args.SetInt(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS, config_.isKeepAliveWithoutCalls() ? 1 : 0);
    }
    
    std::shared_ptr<::grpc::ChannelCredentials> creds;
    if (config_.isEnableTls()) {
        creds = ::grpc::SslCredentials(::grpc::SslCredentialsOptions());
    } else {
        creds = ::grpc::InsecureChannelCredentials();
    }
    
    return ::grpc::CreateCustomChannel(target, creds, args);
}

std::unique_ptr<::grpc::ClientContext> GrpcClient::createContext() {
    auto context = std::make_unique<::grpc::ClientContext>();
    
    // 设置超时
    auto deadline = std::chrono::system_clock::now() + 
                   std::chrono::milliseconds(config_.getReadTimeout());
    context->set_deadline(deadline);
    
    // 设置压缩
    if (config_.isEnableCompression()) {
        context->set_compression_algorithm(GRPC_COMPRESS_GZIP);
    }
    
    return context;
}

void GrpcClient::handleGrpcStatus(const ::grpc::Status& status) {
    if (!status.ok()) {
        std::stringstream ss;
        ss << "gRPC错误: " << status.error_code() << " - " << status.error_message();
        throw ConnectionException(ss.str());
    }
}

} // namespace kwdb
